package config

import (
	"fmt"
	"reflect"

	"github.com/pkg/errors"
	"github.com/spf13/viper"
)

const tagViper = "viper"

func viperParse(cfg interface{}, vip *viper.Viper) error {
	v := reflect.ValueOf(cfg)
	if v.Kind() != reflect.Ptr {
		return errors.New("cfg is not pointer")
	}
	v = v.Elem()
	return value(v, vip)
}

func value(v reflect.Value, vip *viper.Viper) error {
	for i := 0; i < v.NumField(); i++ {
		field := v.Type().Field(i)
		name := field.Tag.Get(tagViper)
		if name == "" {
			return errors.Errorf("empty viper key for %v", field.Name)
		}
		//如果要支持time.Time等其他类型，这里不使用Kind()，而是直接用.(type)
		switch v.Field(i).Kind() {
		case reflect.String:
			v.Field(i).SetString(vip.GetString(name))
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			v.Field(i).SetInt(vip.GetInt64(name))
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			v.Field(i).SetUint(vip.GetUint64(name))
		case reflect.Bool:
			v.Field(i).SetBool(vip.GetBool(name))
		case reflect.Float32, reflect.Float64:
			v.Field(i).SetFloat(vip.GetFloat64(name))
		case reflect.Struct:
			fmt.Println(v.Field(i).Kind())
			err := value(v.Field(i), vip.Sub(name))
			if err != nil {
				return err
			}
		default:
			/*
				iface:=vip.Get(name)
				gotv := reflect.ValueOf(iface)
				if !gotv.Type().AssignableTo(field.Type) {
					return fmt.Errorf("wrong type for %v", field.Name)
				}
				v.Field(i).Set(gotv)
			*/
			return errors.Errorf("not support,please implement,type:%s", v.Type())
		}
	}

	return nil
}
